package io.kimmking.sso.ssodemo;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@WebFilter(urlPatterns = "/*", filterName = "loginFilter")
public class LoginFilter implements Filter {

    private static CloseableHttpClient httpclient;
    public static String CHARSET = "UTF-8";

    Map<String,String> map = new HashMap<>();

    @Value("${cas.url}")
    String casUrl;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Filter初始化中");
        System.out.println("casUrl:" + casUrl);

        RequestConfig config = RequestConfig.custom().setConnectTimeout(5000).setSocketTimeout(3000).build();
        httpclient = HttpClientBuilder.create().setDefaultRequestConfig(config).build();

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String path = request.getRequestURL().toString();

        // 模拟 业务系统 a.cn 想要访问资源
        if(path.indexOf("/book") > -1){
            String token = request.getParameter("_token");
            if(null == token) {

                // 未登录时，要跳转到CAS去做登录操作
                System.out.println("A1.未登录访问 http://a.cn/book");
                String casLogin = "http://" + casUrl + "/login.html?redirect=" + response.encodeRedirectURL(path);
                System.out.println("A2.跳转到 " + casLogin);
                response.sendRedirect(casLogin);

                return ;
            }else {

                // 在CAS登录后跳转回来时，带了token，需要去CAS验证token，获取用户信息
                System.out.println("A3.已登录访问 http://a.cn/book , _token=" + token);

                HttpGet httpGet = new HttpGet("http://" + casUrl + "/sso?_token=" + token);
                CloseableHttpResponse res = httpclient.execute(httpGet);
                String username = EntityUtils.toString(res.getEntity(), "utf-8");
                if(null != username) {
                    System.out.println("A4.从cas获取信息_token=" + token + ",username=" + username);
                    System.out.println("A5.登录成功，可以访问 http://a.cn/book");
                    request.getSession(true).setAttribute("A_USERNAME", username);

                }else{
                    response.sendError(428,"not permitted");
                    System.out.println("A6.登录失败，cas中token对应用户信息不存在:" + token);
                }

            }
        }

        // 模拟CAS c.cn的登录处理
        if(path.indexOf("/cas") > -1){

            // 模拟验证用户名密码
            String username = request.getParameter("username");
            String password = request.getParameter("password");

            System.out.println("C1: CAS 登录成功！！！username=" + username);

            // 模拟生成token UUID
            String token = UUID.randomUUID().toString();
            System.out.println("C2: 为用户"+ username+"生成token=" + token);
            map.put(token,username); // 可以存入redis等cache

            request.getSession(true).setAttribute("C_USERNAME", username);

            // 通过传递过来的redirect url，跳转回原先的请求业务系统a.cn
            String redirect = request.getParameter("redirect");
            if(redirect.indexOf("?redirect=") > 0) {
                redirect = redirect.substring(redirect.indexOf("?redirect=")+10);
            }

            System.out.println("C3: 跳转回原请求redirect=" + redirect);

            response.sendRedirect(redirect+"?_token=" + token );
            return ;
        }


        // 模拟CAS c.cn的通过token获取用户信息的服务端
        if(path.indexOf("/sso") > -1){
            String token = request.getParameter("_token");
            String username = map.get(token);

            System.out.println("C4：验证token是否有效 " + token + ", username=" + username);

            response.getWriter().println(username); // 如果传递更多信息，这里需要使用一个json
            response.flushBuffer();
            return ;
        }

        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        System.out.println("Filter销毁中");
    }
}
